package com.colin.juc.designmode;

import cn.hutool.http.HttpResponse;

import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;

/**
 * @author zhaodong 2021/6/4 19:0623
 * email: colinzhaodong@gmail.com
 * desc:
 */
public class GuardedObject<T> {
    // 受保护的对象
    T obj;
    final Lock lock =
            new ReentrantLock();
    final Condition done =
            lock.newCondition();
    final int timeout=2;
    // 保存所有 GuardedObject
    final static Map<Object, GuardedObject>
            gos=new ConcurrentHashMap<>();
    final static Map<Object, Message> contentMap =new ConcurrentHashMap<>();
    // 静态方法创建 GuardedObject
    static <K> GuardedObject create(K key){
        GuardedObject go=new GuardedObject();
        gos.put(key, go);
        return go;
    }
    static <K, T> void
    fireEvent(K key, T obj){
        GuardedObject go=gos.remove(key);
        if (go != null){
            go.onChanged(obj);
        }
    }
    // 获取受保护对象
    T get(Predicate<T> p) {
        lock.lock();
        try {
            int num = 0;
            //MESA 管程推荐写法
            while(!p.test(obj)){
                done.await(timeout,
                        TimeUnit.SECONDS);
                num++;
                //循环等待3次推出
                if (num > 3){
                    System.out.println("超时");
                    break;
                }
            }
        }catch(InterruptedException e){
            throw new RuntimeException(e);
        }finally{
            lock.unlock();
        }
        // 返回非空的受保护对象
        return obj;
    }
    // 事件通知方法
    void onChanged(T obj) {
        lock.lock();
        try {
            this.obj = obj;
            done.signalAll();
        } finally {
            lock.unlock();
        }
    }


//    // 处理浏览器发来的请求
    private  Message handleWebReq(){
        String id= UUID.randomUUID().toString();
        // 创建一消息
        Message msg1 = new
                Message(id,"测试消息");
        // 创建 GuardedObject 实例
        GuardedObject<Message> go=
                GuardedObject.create(id);
        // 发送消息
        send(msg1);
        // 等待 MQ 消息
        return go.get(
                Objects::nonNull);
    }
    void onMessage(Message msg){
        // 唤醒等待的线程
        GuardedObject.fireEvent(
                msg.id, msg);
    }

    private void send(Message msg){
        System.out.println(msg.getMsg());
        //消费消息
        onMessage(msg);
    }

    public static void main(String[] args) {
        GuardedObject guardedObject = new GuardedObject();
        Message message = guardedObject.handleWebReq();
        System.out.println(message.getMsg());
    }


}
